{% extends "base.html" %}
{% import "bootstrap/wtf.html" as wtf %}
{% import "_macros.html" as macros %}

{% block title %}语音识别模型基准测试系统{% endblock %}

{% block page_content %}
<div class="page-header">
    <a href="{{ url_for('.acoustic_model') }}">返回声学模型总页</a>
    <p id="acoustic-model-id" style="display:none">{{ acoustic_model.id }}</p>
    <p>名称: {{ acoustic_model.name }}</p>
    <p>备注：<span id="note_span">{{ acoustic_model.note }}</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span id="add_note_button_span"><a href="javascript:void(0);" onclick="show_finish_add_note({{ acoustic_model.id }})"><button>添加备注</button></a></span><span id="show_finish_add_note_span"></span></p>
    <p>类型: {% if acoustic_model.typ==0 %}深度学习{% elif acoustic_model.typ==1 %}基于深度神经网络和隐马尔科夫的混合模型{% elif acoustic_model.typ==2 %}基于高斯混合和隐马尔科夫的混合模型{% endif %}</p>
    <p>内容: {% if acoustic_model.content==0 %}结构{% elif acoustic_model.content==1 %}结构+权重{% endif %}</p>
    <p>文件路径：{{ acoustic_model.file }}</p>
    <p>文件类型: {% if acoustic_model.filetype==0 %}源代码{% if acoustic_model.framework==0 %}<a class="btn btn-default" href="javascript:void(0);" onclick="start_gen('config',{{ acoustic_model.id }})">生成config网络结构文件</a><a class="btn btn-default" href="javascript:void(0);" onclick="start_gen('json',{{ acoustic_model.id }})">生成json网络结构文件</a>{% endif %}{% elif acoustic_model.filetype==1 %}深度学习框架导出的模型文件{% endif %}</p>
    {% if acoustic_model.weights_file %}
    <p>权重文件路径：{{ acoustic_model.weights_file }}</p>
    <p>权重类型：{% if acoustic_model.weights_type==0 %}keras权重{% elif acoustic_model.weights_type==1 %}keras检查点{% elif acoustic_model.weights_type==2 %}pytorch字典{% endif %}</p>
    {% endif %}
    {% if acoustic_model.filetype==0 %}<p>源代码中的模块名：{{ acoustic_model.modulename }}</p>
    <p>源代码中的模块的全局函数名：{{acoustic_model.classname }}</p>
    <p>源代码中的全局函数的参数列表：{{ acoustic_model.parameters }}</p>
    {% if acoustic_model.attribute %}
    <p>源代码中的[函数名(参数列表)]：{{ acoustic_model.attribute }}</p>
    {% endif %}
    <pre id="model-code-pre" style="display:none;"></pre>
    <a class="btn btn-default" href="javascript:void(0)" onclick="get_code('{{ acoustic_model.modulename }}','{{ acoustic_model.classname }}','model')">获取声学模型的源代码</a>
    {% if acoustic_model.infer_classname %}
    <p>推理模型源代码的模块的全局函数名：{{ acoustic_model.infer_classname }}</p>
    <p>推理模型源代码的全局函数的参数列表：{{ acoustic_model.infer_parameters }}</p>
    {% if acoustic_model.infer_attribute %}
    <p>推理模型源代码的[函数名(参数列表)]：{{ acoustic_model.infer_attribute }}</p>
    {% endif %}
    <pre id="infer-model-code-pre" style="display:none;"></pre>
    <a class="btn btn-default" href="javascript:void(0)" onclick="get_code('{{ acoustic_model.modulename }}','{{ acoustic_model.infer_classname }}','infer-model')">获取推理声学模型的源代码</a><br>
    {% endif %}
    {% elif acoustic_model.filetype==1 %}
    <p>深度学习框架导出的模型文件的加载方式：{% if acoustic_model.file_ext==0 %}saved_model格式{% elif acoustic_model.file_ext==1 %}json格式{% elif acoustic_model.file_ext==2 %}config格式{% elif acoustic_model.file_ext==3 %}pytroch模型格式{% endif %}</p>{% endif %}
    <p>所使用的深度学习框架：{% if acoustic_model.framework==0 %}tf.keras{% elif acoustic_model.framework==1 %}torch.nn{% elif acoustic_model.framework==2 %}transformers.Wav2Vec2ForCTC{% endif %}</p>
    {% if acoustic_model.infer_input_layer_names or acoustic_model.infer_output_layer_names %}
    <p>推理模型的输入节点名称：{{ acoustic_model.infer_input_layer_names }}</p>
    <p>推理模型的输出节点名称：{{ acoustic_model.infer_output_layer_names }}</p>
    {% endif %}
    {% if acoustic_model.optimizer_modulename %}
    <p>（模型参数）优化器所在的模块名：{{ acoustic_model.optimizer_modulename }}</p>
    <p>实现（模型参数）优化器的模块的全局函数名：{{ acoustic_model.optimizer_classname }}</p>
    <p>实现（模型参数）优化器的全局函数的参数列表：{{ acoustic_model.optimizer_parameters }}</p>
    {% if acoustic_model.optimizer_attribute %}
    <p>实现（模型参数）优化器的[函数名(参数列表)]：{{ acoustic_model.optimizer_attribute }}</p>
    {% endif %}
    <pre id="optimizer-code-pre" style="display:none;"></pre>
    <a class="btn btn-default" href="javascript:void(0)" onclick="get_code('{{ acoustic_model.optimizer_modulename }}','{{ acoustic_model.optimizer_classname }}','optimizer')">获取模型参数优化器的源代码</a>
    {% endif %}
    {% if acoustic_model.loss_modulename %}
    <p>（模型）损失计算函数所在的模块名：{{ acoustic_model.loss_modulename }}</p>
    <p>实现（模型）损失计算函数的模块的全局函数名：{{ acoustic_model.loss_classname }}</p>
    <p>实现（模型）损失计算函数的全局函数的参数列表：{{ acoustic_model.loss_parameters }}</p>
    {% if acoustic_model.loss_attribute %}
    <p>实现（模型）损失计算函数的[函数名(参数列表)]：{{ acoustic_model.loss_attribute }}</p>
    {% endif %}
    <pre id="loss-code-pre" style="display:none;"></pre>
    <a class="btn btn-default" href="javascript:void(0)" onclick="get_code('{{ acoustic_model.loss_modulename }}','{{ acoustic_model.loss_classname }}','loss')">获取模型损失函数的源代码</a>
    {% endif %}
    <p id="structure">网络结构：{{ acoustic_model.structure }}</p>
    {% if acoustic_model.framework==0 %}
    <p id="inputs">输入节点：{{ acoustic_model.inputs }}</p>
    <p id="outputs">输出节点：{{ acoustic_model.outputs }}</p>
    {% endif %}
    <p id="param">参数数量：总共{{ acoustic_model.param_total }}，可训练参数{{ acoustic_model.param_trainable }}，不可训练参数{{ acoustic_model.param_non }}</p>
    <p id="flops">浮点数运算量：<span id="flops_span">{{ acoustic_model.flops }}</span>{% if acoustic_model.framework==1 and acoustic_model.flops==-1 %}<span id="input-shape-err-msg" style="color:red;"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span id="cal_flops_button_span"><a href="javascript:void(0)" onclick="show_finish_cal_flops({{ acoustic_model.id }})"><button>计算模型的浮点数运算量</button></a></span><span id="show_finish_cal_flops_span"></span>{% endif %}</p>
    <a class="btn btn-default" href="javascript:void(0)" onclick="start_get_acoustic_model_network({{ acoustic_model.id }})">开始处理声学模型的网络结构</a>
    <a class="btn btn-default" href="{{ url_for('.acoustic_model_edit',id=acoustic_model.id) }}">修改声学模型信息</a>
    <a class="btn btn-default" href="{{ url_for('.acoustic_model_json',id=acoustic_model.id) }}">导出声学模型的json配置文件</a><br>
    <a class="btn btn-default" href="{{ url_for('.acoustic_model_active',id=acoustic_model.id) }}">更新活动时间</a>
    <a class="btn btn-default" href="{{ url_for('.acoustic_model_copy',id=acoustic_model.id) }}">以此为模版新建</a><br>
    
    <span id="span-1"></span><br>
    <span id="span-2"></span><br>
    <span id="span-3"></span>
    {% if model_names %}
    <p>
        使用本声学模型的语音识别模型是<br>
        {% for i in range(model_names|length) %}
        <a href="{{ url_for('.m',id=model_ids[i]) }}">{{ model_names[i] }}</a>，
        {% endfor %}
    </p>
    {% endif %}
</div>
<script type="text/javascript">
    function update_gen_status(status_url){
        $.getJSON(status_url,function(data){
            $('#span-1').text($('#span-2').text());
            $('#span-2').text($('#span-3').text());
            if('result' in data){
                $('#span-3').text(data['time']+' '+data['result']+' '+data['status']);
            }else{
                $('#span-3').text(data['time']+' '+data['state']+' '+data['status']);
            }
            if(data['state']=='PENDING'||data['state']=='PROGRESS'){
                setTimeout(function(){
                    update_gen_status(status_url);
                },1000);
            }
        });
    }

    function start_gen(typ,acoustic_model_id){
        $.ajax({
            type:'POST',
            url:'/gen_'+typ+'/'+acoustic_model_id,
            success:function(data,status,request){
                status_url=request.getResponseHeader('Location');
                update_gen_status(status_url);
            },
            error:function(){
                alert('请求转换声学模型网络结构为'+typ+'类型的文件的过程中出现错误');
            }
        });
    }

    function start_get_acoustic_model_network(acoustic_model_id){
        $.ajax({
            type:'POST',
            url:'/get_acoustic_model_network/'+acoustic_model_id,
            success:function(data,status,request){
                status_url=request.getResponseHeader('Location');
                update_status(status_url);
            },
            error:function(){
                alert('请求获取声学模型的网络结构的过程中出现错误');
            }
        });
    }
    function update_status(status_url){
        $.getJSON(status_url,function(data){
            $('#span-1').text($('#span-2').text());
            $('#span-2').text($('#span-3').text());
            if ('result' in data){
                if (data['status']!='error'){
                    $('#span-3').text(data['time']+' '+data['status']);
                    let result=$.parseJSON(data['result']);
                    console.log(result);
                    $('#structure').text('网络结构：'+result['structure']);
                    $('#inputs').text('输入节点：'+result['inputs']);
                    $('#outputs').text('输出节点：'+result['outputs']);
                    $('#param').text('参数数量：总共'+result['param_total']+'，可训练参数'+result['param_trainable']+'，不可训练参数'+result['param_non']);
                    $('#flops').text('浮点数运算量：'+result['flops']);
                }else{
                    $('#span-3').text(data['time']+' '+data['status']+' '+data['result']);
                }
            }else{
                $('#span-3').text(data['time']+' '+data['state']+' '+data['status']);
            }
            if(data['state']=='PENDING'||data['state']=='PROGRESS'){
                setTimeout(function(){
                    update_status(status_url);
                },1000);
            }
        });
    }

    function update_get_code_status(status_url,typ){
        $.getJSON(status_url,function(data){
            $('#span-1').text($('#span-2').text());
            $('#span-2').text($('#span-3').text());
            if('result' in data){
                console.log(data);
                $('#'+typ+'-code-pre').attr('style','display:block;');
                $('#'+typ+'-code-pre').text(data['result']);
            }else{
                $('#span-3').text(data['time']+' '+data['state']+' '+data['status']);
            }
            if(data['state']=='PENDING'||data['state']=='PROGRESS'){
                setTimeout(function(){
                    update_get_code_status(status_url,typ);
                },1000);
            }
        });
    }

    function get_code(modulename,classname,typ){
        $.ajax({
            type:'POST',
            url:'/get_code?modulename='+modulename+'&classname='+classname,
            success:function(data,status,request){
                status_url=request.getResponseHeader('Location');
                update_get_code_status(status_url,typ);
            },
            error:function(){
                alert('获取'+modulename+'的'+classname+'类/函数区块代码的过程中出现错误');
            }
        });
    }

    function update_cal_pytorch_model_flops_status(url){
        $.getJSON(url,function(data){
            $('#span-1').text($('#span-2').text());
            $('#span-2').text($('#span-3').text());
            if('result' in data){
                $('#span-3').text(data['time']+' '+data['status']+' '+data['result']);
                $('#flops_span').html(data['result']);
            }else{
                $('#span-3').text(data['time']+' '+data['state']+' '+data['status']);
            }
            if(data['state']=='PENDING'||data['state']=='PROGRESS'){
                setTimeout(function(){
                    update_cal_pytorch_model_flops_status(url);
                },1000);
            }
        });
    }

    function show_finish_cal_flops(acoustic_model_id){
        $('#cal_flops_button_span').html('');
        $('#show_finish_cal_flops_span').html('<input id="cal_flops_input" style="width:200px;" placeholder="用英文逗号分隔输入张量的各个维度大小，例如填写1,128,1000，不用填写批量大小的维度"><a href="javascript:void(0)" onclick="cal_flops('+acoustic_model_id+')"><button>完成</button></a>');
    }

    function cal_flops(acoustic_model_id){
        var input_shape_regs=/^(\d+,)*\d+$/;
        if(!input_shape_regs.test($('#rename_input').val())){
            $('#input-shape-err-msg').text('模型输入数据的形状格式不规范');
            return;
        }
        $.ajax({
            type:'GET',
            url:'/cal_pytorch_model_flops?input_shape='+$('#cal_flops_input').val()+'&acoustic_model_id='+test_project_id,
            success:function(data,status,request){
                update_cal_pytorch_model_flops_status(data);
            },
            error:function(){
                alert('请求重命名测试项目的过程中出现错误');
            }
        });
        $('#cal_flops_button_span').html('<a href="javascript:void(0)" onclick="show_finish_cal_flops({{ acoustic_model.id }})"><button>计算模型的浮点数运算量</button></a>');
        $('#show_finish_cal_flops_span').html('');
    }

    function show_finish_add_note(acoustic_model_id){
        $('#add_note_button_span').html('');
        $('#show_finish_add_note_span').html('<input id="note_input" style="width:200px;" value="'+$('#note_span').text()+'"><a href="javascript:void(0)" onclick="add_note('+acoustic_model_id+')"><button>完成</button></a>');
    }

    function add_note(acoustic_model_id){
        $.ajax({
            type:'GET',
            url:'/add_acoustic_model_note?note='+$('#note_input').val()+'&acoustic_model_id='+acoustic_model_id,
            success:function(data,status,request){
                $('#note_span').html($('#note_input').val());
            },
            error:function(){
                alert('请求添加声学模型的备注的过程中出现错误');
            }
        });
        $('#add_note_button_span').html('<a href="javascript:void(0)" onclick="show_finish_add_note('+acoustic_model_id+')"><button>添加备注</button></a>');
        $('#show_finish_add_note_span').html('');
    }
</script>
{% if not is_initialized %}
<script type="text/javascript">
    window.onload=function(){
        start_get_acoustic_model_network(parseInt($('#acoustic-model-id').text()));
    };
</script>
{% endif %}
{% endblock %}